# -*- coding: UTF-8 -*-
"""
HaaS506 DTU - 数据收集和存储服务（精简版）
优化为仅使用 flash 文件持久化，不使用内存队列，节省资源
"""
"""
1表示 可以，0表示不行
_____________________________________________
模式      r     r+      w      w+     a    a+
读        1     1       0      1      0    1
写        0     1       1      1      1    1
创建      0     0       1      1      1    1
覆盖      0     0       1      1      0    0
指针在头  1     1       1      1      0    0
指针在尾  0     0       0      0      1    1 
_____________________________________________
"""

import mod_time
import utime as time
import gc
import mod_485
from modem import sim
import ujson
import config
import mod_network
import mod_adc
import service_storage
import mod_system
import mod_mqtt

# temp_data = None
# power_data = None
# network_data = None
# system_data = None
# formatted_data = None


def format_float(value, decimal_places=1):
    try:
        if value is None:
            return -999.0
        return round(float(value), decimal_places)
    except (ValueError, TypeError):
        return -999.0


def format_temperature(temp_value):
    return format_float(temp_value, 1)


def format_humidity(humidity_value):
    return format_float(humidity_value, 1)


class DataCollectionService:

    def collect_adc_data(self):
        try:
            adc_power = mod_adc.get_di1_value()
            return {
                "adc_power": adc_power,
                "status": "OK",
                "timestamp": time.time(),
            }
        except Exception as e:
            print("[DATA_SERVICE] ADC error:", e)
            return {
                "adc_power": -999,
                "status": "EXCEPTION",
                "timestamp": time.time(),
                "error": str(e),
            }

    def collect_data(self):
        data = self.collect_comprehensive_data()

        print("[MAIN] Data collection OK, data:{}".format(data))
        # if config.g_mqtt_connected:
        if mod_mqtt.is_connected():
            success = mod_mqtt.publish_data(data)
            if success:
                print("[MAIN] MQTT publish Success, data: {}".format(data))
            else:
                print("[MAIN] MQTT publish Error, store data")
                # 直接存储到flash，避免重启丢失
                self.store_data(data)
                self.check_cache_overflow()
        else:
            self.store_data(data)
            self.check_cache_overflow()

    def check_cache_overflow(self):
        # 如果缓存的数据太多（100的整数倍），就重启一下设备（可能网络问题等）
        if self.flash_data_count() > 99 and self.flash_data_count() % 100 == 0:
            print("[MAIN] Data cache overflow, restart device")
            mod_system.restart()

    def push_data(self):
        pending_data = self.get_pending_data(10)
        for data in pending_data:
            if hasattr(mod_mqtt, "publish_data"):
                success = mod_mqtt.publish_data(data)
                if success:
                    self.mark_data_uploaded(1)
                    print("[MAIN] MQTT upload OK")
                else:
                    print("[MAIN] MQTT upload failed")
                    break
        # 清理 pending_data 占用的内存
        pending_data = None

    def collect_temperature_data(self):
        try:
            temp_data = mod_485.read_temperature_sensor()
            if temp_data:
                return {
                    "temperature": format_temperature(temp_data.get("temperature")),
                    "humidity": format_humidity(temp_data.get("humidity")),
                    "status": "OK",
                    "timestamp": time.time(),
                }
            else:
                return {
                    "temperature": -999,
                    "humidity": -999,
                    "status": "ERROR",
                    "timestamp": time.time(),
                }
        except Exception as e:
            print("[DATA_SERVICE] Temperature error:", e)
            return {
                "temperature": -999,
                "humidity": -999,
                "status": "EXCEPTION",
                "timestamp": time.time(),
                "error": str(e),
            }

    def collect_power_data(self):
        try:
            power_data = mod_485.read_complete_power_data()
            if power_data:
                return {
                    "voltage_a": power_data.get("voltage_a", -999),
                    "voltage_b": power_data.get("voltage_b", -999),
                    "voltage_c": power_data.get("voltage_c", -999),
                    "current_a": power_data.get("current_a", -999),
                    "current_b": power_data.get("current_b", -999),
                    "current_c": power_data.get("current_c", -999),
                    "volt": power_data.get("volt", -999),
                    "current": power_data.get("current", -999),
                    "energy": power_data.get("energy", -999),
                    "status": "OK",
                    "timestamp": time.time(),
                }
            else:
                return {
                    k: -999
                    for k in [
                        "voltage_a",
                        "voltage_b",
                        "voltage_c",
                        "current_a",
                        "current_b",
                        "current_c",
                        "volt",
                        "current",
                        "energy",
                    ]
                }
        except Exception as e:
            print("[DATA_SERVICE] Power error:", e)
            return {
                "voltage_a": -999,
                "voltage_b": -999,
                "voltage_c": -999,
                "current_a": -999,
                "current_b": -999,
                "current_c": -999,
                "volt": -999,
                "current": -999,
                "energy": -999,
                "status": "EXCEPTION",
                "timestamp": time.time(),
                "error": str(e),
            }

    def collect_network_data(self):
        try:
            network_status = mod_network.get_network_status()
            iccid = "unknown"
            try:
                iccid = sim.getIccid()
            except:
                pass

            if network_status:
                return {
                    "connected": network_status.get("connected", False),
                    "signal_strength": network_status.get("signal_strength", -999),
                    "iccid": iccid,
                    "status": "OK",
                    "timestamp": time.time(),
                    "registered": network_status.get("registered", False),
                    "total_connections": network_status.get("total_connections", 0),
                    "connection_failures": network_status.get("connection_failures", 0),
                }
            else:
                return {
                    "connected": False,
                    "signal_strength": -999,
                    "iccid": iccid,
                    "status": "ERROR",
                    "timestamp": time.time(),
                }
        except Exception as e:
            print("[DATA_SERVICE] Network error:", e)
            return {
                "connected": False,
                "signal_strength": -999,
                "iccid": "unknown",
                "status": "EXCEPTION",
                "timestamp": time.time(),
                "error": str(e),
            }

    def collect_system_data(self):
        try:
            free_mem = gc.mem_free()
            alloc_mem = gc.mem_alloc()
            device_sn = config.get_device_sn()
            reboot_count = service_storage.runtime_storage.get_reboot_count()
            return {
                "free_memory": free_mem,
                "allocated_memory": alloc_mem,
                "device_sn": device_sn,
                "reboot_count": reboot_count,
                "timestamp": time.time(),
                "status": "OK",
            }
        except Exception as e:
            print("[DATA_SERVICE] System error:", e)
            return {
                "free_memory": -999,
                "allocated_memory": -999,
                "device_sn": "unknown",
                "reboot_count": -999,
                "timestamp": time.time(),
                "status": "EXCEPTION",
                "error": str(e),
            }

    def collect_comprehensive_data(self):
        try:
            temp_data = self.collect_temperature_data()
            power_data = self.collect_power_data()
            network_data = self.collect_network_data()
            system_data = self.collect_system_data()
            adc_data = self.collect_adc_data()

            formatted_data = self.format_data(
                temperature=temp_data.get("temperature"),
                humidity=temp_data.get("humidity"),
                iccid=network_data.get("iccid"),
                volt=power_data.get("volt"),
                current=power_data.get("current"),
                energy=power_data.get("energy"),
                signal_strength=network_data.get("signal_strength"),
                adc_power=adc_data.get("adc_power"),
                for_mqtt=False,
            )

            formatted_data.update(
                {
                    "device_sn": system_data.get("device_sn"),
                }
            )

            return formatted_data
        except Exception as e:
            print("[DATA_SERVICE] Comprehensive error:", e)
            return None

    def clear_all_data(self):
        # 清除flash数据缓存
        try:
            with open("/flash/data_cache.txt", "w") as f:
                f.write("")
            print("[DATA_SERVICE] All data cleared")
        except Exception as e:
            print("[DATA_SERVICE] Clear all data error:", e)

    def store_data(self, data):
        try:
            with open("/flash/data_cache.txt", "a") as f:
                f.write(ujson.dumps(data) + "\n")
                print("[DATA_SERVICE] Data stored to flash,data:{}".format(data))
            return True
        except Exception as e:
            print("[DATA_SERVICE] Store data error:", e)
            return False

    def clear_max_data(self):
        # 清除flash数据缓存
        try:
            with open("/flash/data_cache.txt", "r") as f:
                lines = f.readlines()
            max_queue_size = config.get_config("system.max_queue_size")
            if len(lines) > max_queue_size:
                with open("/flash/data_cache.txt", "w") as f:
                    f.write("".join(lines[-max_queue_size:]))

        except Exception as e:
            print("[DATA_SERVICE] Clear max data error:", e)

    def get_pending_data(self, limit=None):
        try:
            result = []
            with open("/flash/data_cache.txt", "r") as f:
                for line in f:
                    if line.strip():
                        try:
                            result.append(ujson.loads(line))
                            if limit and len(result) >= limit:
                                break
                        except:
                            continue
            return result
        except Exception as e:
            print("[DATA_SERVICE] Read flash error:", e)
            return []

    def mark_data_uploaded(self, count):
        """删除缓存文件前 count 行，表示这些数据已上传"""
        try:
            with open("/flash/data_cache.txt", "r") as f:
                lines = f.readlines()

            if count >= len(lines):
                # 所有数据都已上传，清空文件
                with open("/flash/data_cache.txt", "w") as f:
                    f.write("")
                print("[DATA_SERVICE] All data uploaded, cache cleared")
            else:
                # 保留剩余数据
                with open("/flash/data_cache.txt", "w") as f:
                    for line in lines[count:]:
                        f.write(line)
                print("[DATA_SERVICE] Removed {} lines from flash".format(count))

            return True

        except Exception as e:
            print("[DATA_SERVICE] Mark uploaded error:", e)
            return False

    def flash_data_count(self, filename="/flash/data_cache.txt"):
        try:
            count = 0
            with open(filename, "r") as f:
                for line in f:
                    if line.strip():
                        count += 1
            return count
        except Exception as e:
            print("[DATA_SERVICE] Count flash error:", e)
            return 0

    def get_data_format(self):
        device_info = config.get_device_info()
        device_sn = device_info.get("device_sn", "10000")
        return {
            "iccid": "00000000000000000000",
            "NO": device_sn,
            "temperature": -999.0,
            "humidity": -999.0,
            "volt": -999.0,
            "current": -999.0,
            "bks": -999,
            "smokeSensor": -999,
            "alarmCurrent": -999,
            "energy": -999.0,
            "uploaded": False,
            "timestamp": 0,
            "datetime": "1970-01-01 08:00:00",
            "signal_strength": 0,
            "adc_power": -999,
        }

    def format_data(
        self,
        temperature=None,
        humidity=None,
        iccid=None,
        volt=None,
        current=None,
        energy=None,
        signal_strength=None,
        adc_power=False,
        for_mqtt=False,
    ):
        data = self.get_data_format()
        data["timestamp"] = mod_time.get_current_beijing_timestamp()
        data["datetime"] = mod_time.get_current_beijing_time()
        if temperature is not None:
            data["temperature"] = round(float(temperature), 1)
        if humidity is not None:
            data["humidity"] = round(float(humidity), 1)
        if iccid is not None:
            data["iccid"] = str(iccid)
        if volt is not None:
            data["volt"] = round(float(volt), 1)
        if current is not None:
            data["current"] = round(float(current), 3 if not for_mqtt else 1)
        if energy is not None:
            data["energy"] = round(float(energy), 2 if not for_mqtt else 1)
        if signal_strength is not None:
            data["signal_strength"] = int(signal_strength)
        if adc_power is not None:
            data["adc_power"] = int(adc_power)

        if for_mqtt:
            data.pop("uploaded", None)
            data.pop("created_at", None)
        return data


# 全局数据存储服务实例
runtime_data_collector = DataCollectionService()
